This notebook documents the process for running the SOT/OTS monthly scripts in R. Preceeding these scripts is a SQL procedure and the end output is a collection of .csv files. The following document will demonstrate the process for creating the Master tables and also the output of a single .csv file.
First we need to load our libraries.
The following code will open a system-independent, file chooser using Java and the function created above. It will allow you to choose the directory in which to save all files. This will sometimes fail the first time it is run. If it fails just rerun it (usualy works the second time). Note: Eval is set to off to disable dynamic functionality for this notebook. This notebook will use the current working directory instead.
Next we need to create a connection to EDWP. Once you have stored your username and password as my_uid and my_pwd; and created a DSN, connect with a string similar to this (You may need to change the below if you gave your DSN an differnet name). Then verify that we have succesfully connected by performing a query on the dbcinfo table.
Next we need to create our master tables via query and store them as R objects.
For the purpose of this notebook, we will not query the database however. Instead, we will load objects already created and stored on an FTP site on the corprate network.
Now let’s load a few static files that will we need for mapping and save the master objects we just created.
And create a few tables for joining.
Lastly we need to output this file as a csv. The file will be output to the directory you set up using the Java file chooser earlier (deactivated for this notebook).
That is it. The basic process is complete. The remaining tables can be created in much the same way.
Appendix
# Create Monthly SOT Brand Table ----
Monthly_Brand_SOT <- SOT_Master %>%
filter(SOT_Master$ShipCancelWeek <= EOW) %>%
group_by(ShipCancelMonth, ReportingBrand) %>%
summarise("SOTUnits" = floor(sum(Units)),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(ShipCancelMonth,
ReportingBrand,
SOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits,
PPAUnits,
PPASOTLateUnits,
PPASOT5daysLateUnits,
WTPPASOTLateUnits)
# View(Monthly_Brand_SOT)
# Create Monthly SOT Category Table ----
Monthly_Category_SOT <- SOT_Master %>%
filter(SOT_Master$ShipCancelWeek <= EOW) %>%
group_by(ShipCancelMonth, Category) %>%
summarise("SOTUnits" = floor(sum(Units)),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(ShipCancelMonth,
Category,
SOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits,
PPAUnits,
PPASOTLateUnits,
PPASOT5daysLateUnits,
WTPPASOTLateUnits)
# View(Monthly_Category_SOT)
# Create Monthly Gap Inc SOT Table ----
Monthly_GapInc_SOT <- SOT_Master %>%
filter(SOT_Master$ShipCancelWeek <= EOW) %>%
group_by(ShipCancelMonth) %>%
summarise("SOTUnits" = floor(sum(Units)),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(ShipCancelMonth,
SOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits,
PPAUnits,
PPASOTLateUnits,
PPASOT5daysLateUnits,
WTPPASOTLateUnits)
# View(Monthly_GapInc_SOT)
# Create Monthly OTS Brand and Category Table ----
Monthly_Brand_Category_OTS <- OTS_Master %>%
filter(OTS_Master$Week <= EOW) %>%
group_by(Month_Number, ReportingBrand, Category) %>%
summarise("OTSUnits" = floor(sum(Units)),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Month_Number,
ReportingBrand,
Category,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits)
# View(Monthly_Brand_Category_OTS)
# Create Monthly OTS Brand Table ----
Monthly_Brand_OTS <- OTS_Master %>%
filter(OTS_Master$Week <= EOW) %>%
group_by(Month_Number, ReportingBrand) %>%
summarise("OTSUnits" = floor(sum(Units)),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Month_Number,
ReportingBrand,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits)
# View(Monthly_Brand_OTS)
# Create Monthly OTS Category Table ----
Monthly_Category_OTS <- OTS_Master %>%
filter(OTS_Master$Week <= EOW) %>%
group_by(Month_Number, Category) %>%
summarise("OTSUnits" = floor(sum(Units)),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Month_Number,
Category,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits)
# View(Monthly_Category_OTS)
# Create Monthly Gap Inc OTS Table ----
Monthly_GapInc_OTS <- OTS_Master %>%
filter(OTS_Master$Week <= EOW) %>%
group_by(Month_Number) %>%
summarise("OTSUnits" = sum(Units),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Month_Number,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits)
# View(Monthly_GapInc_OTS)
# Create Monthly - Preferred Vendor - New ----
Monthly_Preferred_Vendor_new <- inner_join(SOT_Master, Preferred_Vendor_new, by = c("Category"= "New Category", "Parent_Vendor"="Vendor Name")) %>%
filter(ShipCancelWeek <= EOW) %>%
group_by(Category, Parent_Vendor, ShipCancelMonth) %>%
summarise("SOTUnits" = floor(sum(Units)),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(Category,
Parent_Vendor,
ShipCancelMonth,
SOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits,
PPAUnits,
PPASOTLateUnits,
PPASOT5daysLateUnits,
WTPPASOTLateUnits) %>%
arrange(ShipCancelMonth, Category)
# Create Monthly Preferred Vendor - New OTS ----
Monthly_Preferred_Vendor_New_OTS <- inner_join(OTS_Master, Preferred_Vendor_new, by = c("Category"= "New Category", "Parent_Vendor"="Vendor Name")) %>%
filter(Week <= EOW) %>%
group_by(Category, Parent_Vendor, Month_Number ) %>%
summarise("OTSUnits" = floor(sum(Units)),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Category,
Parent_Vendor,
Month_Number,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits) %>%
arrange(Month_Number, Category)
# View(Monthly_Preferred_Vendor_New_OTS)
# Create Monthly Brand and Category Combine Table ----
Monthly_Brand_Category_Combine <- left_join(Monthly_Brand_Category_SOT, Monthly_Brand_Category_OTS, by= c("ShipCancelMonth"="Month_Number", "ReportingBrand"="ReportingBrand", "Category"="Category"))
Monthly_Brand_Category_Combine <- Monthly_Brand_Category_Combine[c(1:8, 13:17,9:10,18,11:12)]
# Create Monthly SOT Brand Combine Table ----
Monthly_Brand_Combine <- left_join(Monthly_Brand_SOT, Monthly_Brand_OTS, by= c("ShipCancelMonth"="Month_Number", "ReportingBrand"="ReportingBrand"))
Monthly_Brand_Combine <- Monthly_Brand_Combine[c(1:7, 12:16, 8:9, 17, 10:11)]
# View(Monthly_Brand_Combine)
# Create Monthly SOT Category Combine Table ----
Monthly_Category_Combine <- left_join(Monthly_Category_SOT, Monthly_Category_OTS, by= c("ShipCancelMonth"="Month_Number", "Category"="Category"))
Monthly_Category_Combine <- Monthly_Category_Combine[c(1:7, 12:16, 8:9, 17, 10:11)]
# View(Monthly_Category_Combine)
# Create Monthly SOT Gap Inc Combine Table ----
Monthly_GapInc_Combine <- left_join(Monthly_GapInc_SOT, Monthly_GapInc_OTS, by= c("ShipCancelMonth"="Month_Number"))
Monthly_GapInc_Combine <- Monthly_GapInc_Combine[c(1:6, 11:15,7:8,16,9:10)]
# View(Monthly_GapInc_Combine)
# Create Preferred Vendor Combine Table ----
Preferred_Vendor_New_Combine <- left_join(Monthly_Preferred_Vendor_new, Monthly_Preferred_Vendor_New_OTS, by = c("Category"="Category", "Parent_Vendor"="Parent_Vendor", "ShipCancelMonth" = "Month_Number"))
Preferred_Vendor_New_Combine <-Preferred_Vendor_New_Combine[c(1:8, 13:17, 9:10, 18, 11:12)]
# Create Monthly - byDC
Monthly_by_DC <- OTS_Master %>%
filter(OTS_Master$Week <= EOW) %>%
group_by(Fiscal_Month, Month_Number, DCCampus, DC_NAME, DestCtryCD) %>%
summarise("Total Units" = floor(sum(Units)),
"OnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTS%" = sum(Units[Lateness=="OnTime"])/sum(Units),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"LateUnits"= floor(sum(Units[Lateness=="Late"]))) %>%
select(Fiscal_Month,
Month_Number,
`OnTimeUnits`,
`Total Units`,
DCCampus,
DC_NAME,
DestCtryCD,
`OTS%`,
`OTSLate5daysUnits`,
`WTOTSLateUnits`,
`LateUnits`)
# Create Top 20 Countries SOT ----
Monthly_Top_20_SOT <- inner_join(SOT_Master, Top_20_Countries, by = c("CountryOfOrigin"= "CountryOfOrigin"))
Monthly_Top_20_SOT <- Monthly_Top_20_SOT %>%
filter(ShipCancelWeek <= EOW) %>%
group_by(ShipCancelMonth) %>%
summarise("SOTUnits" = floor(sum(Units)),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(ShipCancelMonth,
SOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits,
PPAUnits,
PPASOTLateUnits,
PPASOT5daysLateUnits,
WTPPASOTLateUnits)
# View(Monthly_Top_20_SOT)
# Create Monthly Top 20 OTS Table ----
Monthly_TOP_20_OTS <- inner_join(OTS_Master, Top_20_Countries, by = c("ORIGIN_COUNTRY_CODE"="CountryOfOrigin"))
Monthly_TOP_20_OTS <- Monthly_TOP_20_OTS %>%
filter(Week <= EOW) %>%
group_by(Month_Number) %>%
summarise("OTSUnits" = sum(Units),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Month_Number,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits)
# View(Monthly_TOP_20_OTS)
# Create Monthly Top 20 Combine table ----
Monthly_Top_20_Combine <- inner_join(Monthly_Top_20_SOT, Monthly_TOP_20_OTS, by= c("ShipCancelMonth"="Month_Number"))
Monthly_Top_20_Combine <- Monthly_Top_20_Combine[c(1:6, 11:15,7:8,16,9:10)]
# Create Monthly Top 50 Vendors SOT Table ----
Monthly_Top_50_Vendors_SOT <- inner_join(SOT_Master, Top_50_Vendors, by = c("Parent_Vendor"= "Parent_Vendor"))
Monthly_Top_50_Vendors_SOT <- Monthly_Top_50_Vendors_SOT %>%
filter(ShipCancelWeek <= EOW) %>%
group_by(ShipCancelMonth) %>%
summarise("SOTUnits" = floor(sum(Units)),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(ShipCancelMonth,
SOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits,
PPAUnits,
PPASOTLateUnits,
PPASOT5daysLateUnits,
WTPPASOTLateUnits)
# View(Monthly_Top_50_Vendors_SOT)
# Create Monthly Top 50 Vendors OTS Table ----
Monthly_Top_50_Vendors_OTS <- inner_join(OTS_Master, Top_50_Vendors, by = c("Parent_Vendor"= "Parent_Vendor"))
Monthly_Top_50_Vendors_OTS <- Monthly_Top_50_Vendors_OTS %>%
filter(Week <= EOW) %>%
group_by(Month_Number) %>%
summarise("OTSUnits" = sum(Units),
"OTSOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"OTSLateUnits"= floor(sum(Units[Lateness=="Late"])),
"OTSLate5daysUnits" = floor(sum(Units[Lateness=="Late" & Days_Late > 5])),
"WTOTSLateUnits" = floor(sum(Units[Lateness=="Late"]*Days_Late[Lateness=="Late" & Days_Late >=1])),
"PPAOTSLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]))) %>%
select(Month_Number,
OTSUnits,
OTSOnTimeUnits,
OTSLateUnits,
OTSLate5daysUnits,
WTOTSLateUnits,
PPAOTSLateUnits)
# View(Monthly_GapInc_OTS)
# Create Monthly SOT Top 50 Vendors Combine Table ----
Monthly_Top_50_Vendors_Combine <- left_join(Monthly_Top_50_Vendors_SOT, Monthly_Top_50_Vendors_OTS, by= c("ShipCancelMonth"="Month_Number"))
Monthly_Top_50_Vendors_Combine <- Monthly_Top_50_Vendors_Combine[c(1:6, 11:15,7:8,16,9:10)]
# View(Monthly_Top_50__Vendors_Combine)
# Create OTSvsSOT table ----
OTS_vs <- OTS_Master %>%
select(NUMBER_SEQ, Month_Number, Lateness, Units) %>%
filter(Lateness!= "Undetermined") %>%
rename("StockedOnTime" = Lateness) %>%
group_by(Month_Number, StockedOnTime) %>%
droplevels()
SOT_vs <- SOT_Master %>%
select(NUMBER_SEQ, ShipCancelMonth, Lateness) %>%
filter(Lateness!="Unmeasured") %>%
rename("ShippedOnTime" = Lateness) %>%
group_by(ShipCancelMonth, ShippedOnTime) %>%
droplevels()
OTSvsSOT <- inner_join(OTS_vs, SOT_vs, by = c("NUMBER_SEQ"= "NUMBER_SEQ")) %>%
group_by(Month_Number, StockedOnTime, ShippedOnTime) %>%
summarise("SumOfUnits" = floor(sum(Units)))
# Create Monthly Brand Top 10 Delay Combine ----
Brand_Top_Ten_Delay <- SOT_Master %>%
filter(ShipCancelWeek <= EOW) %>%
group_by(ReportingBrand, ShipCancelMonth, Parent_Vendor) %>%
summarise("SOTUnits" = floor(sum(Units)),
"AdjustedSOTUnits"= floor(sum(Units[Lateness=="OnTime"]) + sum(Units[Lateness=="Late"])),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(
ReportingBrand,
ShipCancelMonth,
Parent_Vendor,
SOTUnits,
AdjustedSOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits) %>%
top_n(10, SOTLateUnits) %>%
arrange(ReportingBrand,ShipCancelMonth, desc(SOTLateUnits))
# Create Monthly Category Top 10 Delay Combine ----
Category_Top_Ten_Delay <- SOT_Master %>%
filter(ShipCancelWeek <= EOW) %>%
group_by(Category, ShipCancelMonth, Parent_Vendor) %>%
summarise("SOTUnits" = floor(sum(Units)),
"AdjustedSOTUnits"= floor(sum(Units[Lateness=="OnTime"]) + sum(Units[Lateness=="Late"])),
"SOTOnTimeUnits" = floor(sum(Units[Lateness=="OnTime"])),
"SOTLateUnits"= floor(sum(Units[Lateness=="Late"])),
"SOTLate5daysUnits" = floor(sum(Units[Lateness=="Late" & DAYS_LATE > 5])),
"WTSOTLateUnits" = floor(sum(Units[Lateness=="Late"]*DAYS_LATE[Lateness=="Late" & DAYS_LATE >=1])),
"PPAUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir"])),
"PPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"])),
"PPASOT5daysLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE>5])),
"WTPPASOTLateUnits" = floor(sum(Units[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late"]*DAYS_LATE[SHP_MODE_CATG_NM == "PrepaidAir" & Lateness=="Late" & DAYS_LATE >=1]))) %>%
select(
Category,
ShipCancelMonth,
Parent_Vendor,
SOTUnits,
AdjustedSOTUnits,
SOTOnTimeUnits,
SOTLateUnits,
SOTLate5daysUnits,
WTSOTLateUnits) %>%
top_n(10, SOTLateUnits) %>%
arrange(Category, ShipCancelMonth, desc(SOTLateUnits))
# Write tables ----
write_csv(Monthly_Brand_Category_Combine,
path = paste(SOT_OTS_directory,
paste('Monthly_Brand_Category_Combine_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Monthly_Brand_Combine,
path = paste(SOT_OTS_directory,
paste('Monthly_Brand_Combine_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Monthly_Category_Combine,
path = paste(SOT_OTS_directory,
paste('Monthly_Category_Combine_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Monthly_GapInc_Combine,
path = paste(SOT_OTS_directory,
paste('Monthly_GapInc_Combine_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Preferred_Vendor_New_Combine,
path = paste(SOT_OTS_directory,
paste('Preferred_Vendor_New_Combine_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Monthly_by_DC,
path = paste(SOT_OTS_directory,
paste('Monthly_by_DC_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Monthly_Top_20_Combine,
path = paste(SOT_OTS_directory,
paste('Monthly_Top_20_Countries_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Monthly_Top_50_Vendors_Combine,
path = paste(SOT_OTS_directory,
paste('Monthly_Top_50_Vendors_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(OTSvsSOT,
path = paste(SOT_OTS_directory,
paste('OTSvsSOT_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Brand_Top_Ten_Delay,
path = paste(SOT_OTS_directory,
paste('Brand_Top_10_Delay_WE_', EOW, '.csv',sep = ""), sep = '/' ))
write_csv(Category_Top_Ten_Delay,
path = paste(SOT_OTS_directory,
paste('Category_Top_10_Delay_WE_', EOW, '.csv',sep = ""), sep = '/' ))
LS0tDQp0aXRsZTogIlNPVC9PVFMgTW9udGhseSBOb3RlYm9vayINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KLS0tDQpUaGlzIG5vdGVib29rIGRvY3VtZW50cyB0aGUgcHJvY2VzcyBmb3IgcnVubmluZyB0aGUgU09UL09UUyBtb250aGx5IHNjcmlwdHMgaW4gUi4gUHJlY2VlZGluZyB0aGVzZSBzY3JpcHRzIGlzIGEgU1FMIHByb2NlZHVyZSBhbmQgdGhlIGVuZCBvdXRwdXQgaXMgYSBjb2xsZWN0aW9uIG9mIC5jc3YgZmlsZXMuIFRoZSBmb2xsb3dpbmcgZG9jdW1lbnQgd2lsbCBkZW1vbnN0cmF0ZSB0aGUgcHJvY2VzcyBmb3IgY3JlYXRpbmcgdGhlIE1hc3RlciB0YWJsZXMgYW5kIGFsc28gdGhlIG91dHB1dCBvZiBhIHNpbmdsZSAuY3N2IGZpbGUuIA0KDQpGaXJzdCB3ZSBuZWVkIHRvIGxvYWQgb3VyIGxpYnJhcmllcy4NCmBgYHtyIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KFJPREJDKQ0KbGlicmFyeShmb3JtYXR0YWJsZSkNCmxpYnJhcnkoUkpEQkMpDQpsaWJyYXJ5KHJDaG9pY2VEaWFsb2dzKQ0KDQpgYGANCg0KVGhlbiBzZXQgdXAgb3VyIEVudmlyb25tZW50IHdpdGggYSBmZXcgZnVuY3Rpb25zOg0KYGBge3IgZXZhbD1GQUxTRX0NCiMgc2V0dXAgZW52aXJvbm1lbnQgLS0tLQ0KcHJvbXB0X2Zvcl93ZWVrIDwtIGZ1bmN0aW9uKCkNCnsgDQogIG4gPC0gcmVhZGxpbmUocHJvbXB0PSJFbnRlciBXZWVrIG51bWJlcjogIikNCiAgcmV0dXJuKGFzLmludGVnZXIobikpDQp9DQpjaG9vc2VfZmlsZV9kaXJlY3RvcnkgPC0gZnVuY3Rpb24oKQ0Kew0KICB2IDwtIGpjaG9vc2UuZGlyKCkNCiAgcmV0dXJuKHYpDQp9DQoNCmBgYA0KDQpUaGUgZm9sbG93aW5nIGNvZGUgd2lsbCBvcGVuIGEgc3lzdGVtLWluZGVwZW5kZW50LCBmaWxlIGNob29zZXIgdXNpbmcgSmF2YSBhbmQgdGhlIGZ1bmN0aW9uIGNyZWF0ZWQgYWJvdmUuIEl0IHdpbGwgYWxsb3cgeW91IHRvIGNob29zZSB0aGUgZGlyZWN0b3J5IGluIHdoaWNoIHRvIHNhdmUgYWxsIGZpbGVzLiBUaGlzIHdpbGwgc29tZXRpbWVzIGZhaWwgdGhlIGZpcnN0IHRpbWUgaXQgaXMgcnVuLiBJZiBpdCBmYWlscyBqdXN0IHJlcnVuIGl0ICh1c3VhbHkgd29ya3MgdGhlIHNlY29uZCB0aW1lKS4gTm90ZTogRXZhbCBpcyBzZXQgdG8gb2ZmIHRvIGRpc2FibGUgZHluYW1pYyBmdW5jdGlvbmFsaXR5IGZvciB0aGlzIG5vdGVib29rLiBUaGlzIG5vdGVib29rIHdpbGwgdXNlIHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IGluc3RlYWQuICANCmBgYHtyIGV2YWw9RkFMU0V9DQpTT1RfT1RTX2RpcmVjdG9yeSA8LSBjaG9vc2VfZmlsZV9kaXJlY3RvcnkoKQ0KYGBgDQoNCg0KYGBge3IgZXZhbD1GQUxTRX0NCkVPVyA8LSBwcm9tcHRfZm9yX3dlZWsoKQ0KYGBgDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KRU9XIDwtIDQ4DQoNCmBgYA0KDQpOZXh0IHdlIG5lZWQgdG8gY3JlYXRlIGEgY29ubmVjdGlvbiB0byBFRFdQLiBPbmNlIHlvdSBoYXZlIHN0b3JlZCB5b3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCBhcyBteV91aWQgYW5kIG15X3B3ZDsgYW5kIGNyZWF0ZWQgYSBEU04sIGNvbm5lY3Qgd2l0aCBhIHN0cmluZyBzaW1pbGFyIHRvIHRoaXMgKFlvdSBtYXkgbmVlZCB0byBjaGFuZ2UgdGhlIGJlbG93IGlmIHlvdSBnYXZlIHlvdXIgRFNOIGFuIGRpZmZlcm5ldCBuYW1lKS4gVGhlbiB2ZXJpZnkgdGhhdCB3ZSBoYXZlIHN1Y2Nlc2Z1bGx5IGNvbm5lY3RlZCBieSBwZXJmb3JtaW5nIGEgcXVlcnkgb24gdGhlIGRiY2luZm8gdGFibGUuDQoNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRX0NCiMgQ3JlYXRlIFJPREJDIGNvbm5lY3Rpb24tLS0tIA0KbXlfY29ubmVjdCA8LSBvZGJjQ29ubmVjdChkc249ICJJUCBFRFdQIiwgdWlkPSBteV91aWQsIHB3ZD0gbXlfcHdkKQ0Kc3FsUXVlcnkobXlfY29ubmVjdCwgcXVlcnkgPSAiU0VMRUNUICAqIGZyb20gZGJjLmRiY2luZm87IikNCmBgYA0KV2UgY2FuIHNlZSB0aGF0IHRoZSBzZXJ2ZXIgaGFzIHJldHVybmVkIG91ciB0YWJsZSEgV2UgaGF2ZSBjb25uZWN0ZWQhIA0KDQpOZXh0IHdlIG5lZWQgdG8gY3JlYXRlIG91ciBtYXN0ZXIgdGFibGVzIHZpYSBxdWVyeSBhbmQgc3RvcmUgdGhlbSBhcyBSIG9iamVjdHMuIA0KYGBge3IgZXZhbD1GQUxTRX0NCiMgUXVlcnkgRURXIC0tLS0NClNPVF9NYXN0ZXIgPC0gc3FsUXVlcnkobXlfY29ubmVjdCwgDQogICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5ID0gIlNFTEVDVCAgKiBmcm9tIFNSQUFfU0FORC5WSUVXX1NPVF9NQVNURVI7IikNCg0KT1RTX01hc3RlciA8LSBzcWxRdWVyeShteV9jb25uZWN0LCANCiAgICAgICAgICAgICAgICAgICAgICAgcXVlcnkgPSAiU0VMRUNUICAqIGZyb20gU1JBQV9TQU5ELlZJRVdfT1RTX01BU1RFUjsiKQ0KY2xvc2UobXlfY29ubmVjdCkNCmBgYA0KDQpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBub3RlYm9vaywgd2Ugd2lsbCBub3QgcXVlcnkgdGhlIGRhdGFiYXNlIGhvd2V2ZXIuIEluc3RlYWQsIHdlIHdpbGwgbG9hZCBvYmplY3RzIGFscmVhZHkgY3JlYXRlZCBhbmQgc3RvcmVkIG9uIGFuIEZUUCBzaXRlIG9uIHRoZSBjb3JwcmF0ZSBuZXR3b3JrLiAgDQpgYGB7ciBlY2hvPUZBTFNFfQ0KU09UX2Nvbm4gPC0gdXJsKCJmdHA6Ly9mdHAuZ2FwLmNvbS9kYXRhL3RvX2hxL1N1cHBseUNoYWluUmVwb3J0aW5nL0dTQ0FUL1NPVE1hc3Rlck9iamVjdHMvU09UX01hc3Rlcl9vYmplY3QucnRmIikNCk9UU19jb25uIDwtIHVybCgiZnRwOi8vZnRwLmdhcC5jb20vZGF0YS90b19ocS9TdXBwbHlDaGFpblJlcG9ydGluZy9HU0NBVC9TT1RNYXN0ZXJPYmplY3RzL09UU19NYXN0ZXJfb2JqZWN0LnJ0ZiIpDQogDQpsb2FkKFNPVF9jb25uKQ0KbG9hZChPVFNfY29ubikNCmBgYA0KDQpOb3cgbGV0J3MgbG9hZCBhIGZldyBzdGF0aWMgZmlsZXMgdGhhdCB3aWxsIHdlIG5lZWQgZm9yIG1hcHBpbmcgYW5kIHNhdmUgdGhlIG1hc3RlciBvYmplY3RzIHdlIGp1c3QgY3JlYXRlZC4NCmBgYHtyfQ0KIyBJbXBvcnQgc3RhdGljIGZpbGVzIC0tLS0NClByZWZlcnJlZF9WZW5kb3JfbmV3IDwtIHJlYWRfZGVsaW0oZmlsZSA9ICJmdHA6Ly9mdHAuZ2FwLmNvbS9kYXRhL3RvX2hxL1N1cHBseUNoYWluUmVwb3J0aW5nL0dTQ0FUL1NPVE1hc3Rlck9iamVjdHMvUHJlZmVycmVkIFZlbmRvciAobmV3KS5jc3YiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsaW0gPSAiXiIpDQpDb3VudHJ5X2Rlc2NyaXB0aW9uIDwtIHJlYWRfZGVsaW0oZmlsZT0gImZ0cDovL2Z0cC5nYXAuY29tL2RhdGEvdG9faHEvU3VwcGx5Q2hhaW5SZXBvcnRpbmcvR1NDQVQvU09UTWFzdGVyT2JqZWN0cy9Db3VudHJ5IERlc2NyaXB0aW9uLnR4dCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGltID0gIl4iKQ0KIyBzYXZlIE1hc3RlciBPYmplY3RzIC0tLS0NCnNhdmUoU09UX01hc3RlciwgZmlsZSA9IHBhc3RlKFNPVF9PVFNfZGlyZWN0b3J5LCAgJ1NPVF9NYXN0ZXJfb2JqZWN0LnJ0ZicsIHNlcCA9IC5QbGF0Zm9ybSRmaWxlLnNlcCkpDQpzYXZlKE9UU19NYXN0ZXIsIGZpbGUgPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgICdPVFNfTWFzdGVyX29iamVjdC5ydGYnLCBzZXAgPSAuUGxhdGZvcm0kZmlsZS5zZXAgKSkNCmBgYA0KDQpBbmQgY3JlYXRlIGEgZmV3IHRhYmxlcyBmb3Igam9pbmluZy4NCmBgYHtyfQ0KIyBDcmVhdGUgVE9QIDIwIENvdW50cmllcyBUYWJsZSAtLS0tDQpUb3BfMjBfQ291bnRyaWVzIDwtIGxlZnRfam9pbihTT1RfTWFzdGVyLCBDb3VudHJ5X2Rlc2NyaXB0aW9uLCBieT0gYygiQ291bnRyeU9mT3JpZ2luIj0iQ1RSWV9DRCIgKSkNClRvcF8yMF9Db3VudHJpZXMgPC0gVG9wXzIwX0NvdW50cmllcyAlPiUgDQogIGdyb3VwX2J5KENvdW50cnlPZk9yaWdpbiwgQ1RSWV9ERVNDKSAlPiUgDQogIHN1bW1hcmlzZSgiVW5pdHMgYnkgQ291bnRyeSIgPSBmbG9vcihzdW0oVW5pdHMpKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYFVuaXRzIGJ5IENvdW50cnlgKSkgJT4lIA0KICBoZWFkKDIwKSANCiMgQ3JlYXRlIHRvcCA1MCBWZW5kb3JzIC0tLS0NClRvcF81MF9WZW5kb3JzIDwtIFNPVF9NYXN0ZXIgJT4lIA0KICBncm91cF9ieShQYXJlbnRfVmVuZG9yKSAlPiUgDQogIHN1bW1hcmlzZSgiVW5pdHMgYnkgVmVuZG9yIiA9IGZsb29yKHN1bShVbml0cykpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhgVW5pdHMgYnkgVmVuZG9yYCkpICU+JSANCiAgaGVhZCg1MCkNCmBgYA0KDQoNCkNoZWNrIHRoZSBmaXJzdCA2IHJvd3Mgb2YgU09UIE1hc3RlciB0byB0ZXN0IHRoYXQgb3VyIGxvYWQoKSB3YXMgc3VjY2Vzc3NmdWw6DQpgYGB7cn0NCmhlYWQoU09UX01hc3RlcikNCmBgYA0KDQpPbmNlIHdlIGhhdmUgb3VyIG1hc3RlciB0YWJsZXMgYXMgUiBvYmplY3RzIHdlIG5lZWQgdG8gY2xlYW4gdGhlbSB1cCBhIGJpdDoNCmBgYHtyfQ0KIyBSZW1vdmUgbm9pc2UgZnJvbSBPVFMgYW5kIFNPVCBNYXN0ZXINCk9UU19NYXN0ZXIgPC0gT1RTX01hc3RlciAlPiUgDQogIGZpbHRlcihXZWVrIDw9IEVPVywNCiAgICAgICAgICFncmVwbCgiTGliZXJ0eSBEaXN0cmlidXRpb24iLCBQYXJlbnRfVmVuZG9yLCBpZ25vcmUuY2FzZSA9IFRSVUUpLA0KICAgICAgICAgIWdyZXBsKCJkdW1teSIsIFBhcmVudF9WZW5kb3IsIGlnbm9yZS5jYXNlID0gVFJVRSksDQogICAgICAgICAhZ3JlcGwoIkpQRiIsIERDX05BTUUsIGlnbm9yZS5jYXNlID0gVFJVRSkpIA0KDQpTT1RfTWFzdGVyIDwtIFNPVF9NYXN0ZXIgJT4lIA0KICBmaWx0ZXIoU2hpcENhbmNlbFdlZWsgPD0gRU9XLA0KICAgICAgICAgIWdyZXBsKCJMaWJlcnR5IERpc3RyaWJ1dGlvbiIsIFBhcmVudF9WZW5kb3IsIGlnbm9yZS5jYXNlID0gVFJVRSksDQogICAgICAgICAhZ3JlcGwoImR1bW15IiwgUGFyZW50X1ZlbmRvciwgaWdub3JlLmNhc2UgPSBUUlVFKSwNCiAgICAgICAgIE1ldHJpY1NoaXBEYXRlIDw9IFN5cy5EYXRlKCkpIA0KYGBgDQoNCg0KSW4gdGhlIGFjdHVhbCBzY3JpcHQgX01hc3Rlcl9JbXBvcnQuUl8gdGhlcmUgYXJlIG1hbnkgdGFibGVzIHRoYXQgYXJlIGdlbmVyYXRlZCBmcm9tIHRoZSBhYm92ZSBNYXN0ZXIgdGFibGVzLiBUaGUgZm9sbG93aW5nIGNvZGUgaXMgYW4gZXhhbXBsZSBvZiBvbmUgb3V0cHV0IHRoYXQgd2lsbCBpbGx1c3RyYXRlIHRoZSBwcm9jZXNzIGZvciBhbGwuIFRoZSByZW1haW5pbmcgY29kZSB3aWxsIGJlIHJlc2VydmVkIGZvciB0aGUgYXBwZW5kaXggb2YgdGhpcyBkb2N1bWVudC4NCg0KYGBge3J9DQpNb250aGx5X0JyYW5kX0NhdGVnb3J5X1NPVCA8LSBTT1RfTWFzdGVyICU+JQ0KICBmaWx0ZXIoU09UX01hc3RlciRTaGlwQ2FuY2VsV2VlayA8PSBFT1cpICU+JQ0KICBncm91cF9ieShTaGlwQ2FuY2VsTW9udGgsIFJlcG9ydGluZ0JyYW5kLCBDYXRlZ29yeSkgJT4lIA0KICBzdW1tYXJpc2UoIlNPVFVuaXRzIiA9IGZsb29yKHN1bShVbml0cykpLA0KICAgICAgICAgICAgIlNPVE9uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiU09UTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAiU09UTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPiA1XSkpLCANCiAgICAgICAgICAgICJXVFNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0qREFZU19MQVRFW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpLA0KICAgICAgICAgICAgIlBQQVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIl0pKSwNCiAgICAgICAgICAgICJQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSwgDQogICAgICAgICAgICAiUFBBU09UNWRheXNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURT41XSkpLA0KICAgICAgICAgICAgIldUUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpKSAlPiUgIA0KICBzZWxlY3QoU2hpcENhbmNlbE1vbnRoLCANCiAgICAgICAgIFJlcG9ydGluZ0JyYW5kLCANCiAgICAgICAgIENhdGVnb3J5LCANCiAgICAgICAgIFNPVFVuaXRzLCANCiAgICAgICAgIFNPVE9uVGltZVVuaXRzLCANCiAgICAgICAgIFNPVExhdGVVbml0cywgDQogICAgICAgICBTT1RMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVFNPVExhdGVVbml0cywgDQogICAgICAgICBQUEFVbml0cywNCiAgICAgICAgIFBQQVNPVExhdGVVbml0cywNCiAgICAgICAgIFBQQVNPVDVkYXlzTGF0ZVVuaXRzLA0KICAgICAgICAgV1RQUEFTT1RMYXRlVW5pdHMpDQpgYGANCg0KVGFraW5nIGEgbG9vayBhdCBvdXIgbmV3IHRhYmxlOg0KYGBge3IgZWNobz1GQUxTRX0NCk1vbnRobHlfQnJhbmRfQ2F0ZWdvcnlfU09UW3NhbXBsZSgxOm5yb3coTW9udGhseV9CcmFuZF9DYXRlZ29yeV9TT1QpLCAxMCksIF0NCmBgYA0KDQpMYXN0bHkgd2UgbmVlZCB0byBvdXRwdXQgdGhpcyBmaWxlIGFzIGEgY3N2LiBUaGUgZmlsZSB3aWxsIGJlIG91dHB1dCB0byB0aGUgZGlyZWN0b3J5IHlvdSBzZXQgdXAgdXNpbmcgdGhlIEphdmEgZmlsZSBjaG9vc2VyIGVhcmxpZXIgKGRlYWN0aXZhdGVkIGZvciB0aGlzIG5vdGVib29rKS4gIA0KYGBge3IgZXZhbD1GQUxTRX0NCndyaXRlX2NzdihNb250aGx5X0JyYW5kX0NhdGVnb3J5X0NvbWJpbmUsIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnTW9udGhseV9CcmFuZF9DYXRlZ29yeV9Db21iaW5lX1dFXycsIEVPVywgJy5jc3YnLHNlcCA9ICIiKSwgc2VwID0gJy8nICkpDQpgYGANCg0KVGhhdCBpcyBpdC4gVGhlIGJhc2ljIHByb2Nlc3MgaXMgY29tcGxldGUuIFRoZSByZW1haW5pbmcgdGFibGVzIGNhbiBiZSBjcmVhdGVkIGluIG11Y2ggdGhlIHNhbWUgd2F5Lg0KDQpccGFnZWJyZWFrDQoNCiMjIEFwcGVuZGl4DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQojIENyZWF0ZSBNb250aGx5IFNPVCBCcmFuZCBUYWJsZSAtLS0tDQpNb250aGx5X0JyYW5kX1NPVCA8LSBTT1RfTWFzdGVyICU+JQ0KICBmaWx0ZXIoU09UX01hc3RlciRTaGlwQ2FuY2VsV2VlayA8PSBFT1cpICU+JQ0KICBncm91cF9ieShTaGlwQ2FuY2VsTW9udGgsIFJlcG9ydGluZ0JyYW5kKSAlPiUgDQogIHN1bW1hcmlzZSgiU09UVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzKSksDQogICAgICAgICAgICAiU09UT25UaW1lVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iT25UaW1lIl0pKSwNCiAgICAgICAgICAgICJTT1RMYXRlVW5pdHMiPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0pKSwNCiAgICAgICAgICAgICJTT1RMYXRlNWRheXNVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+IDVdKSksIA0KICAgICAgICAgICAgIldUU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSpEQVlTX0xBVEVbTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+PTFdKSksDQogICAgICAgICAgICAiUFBBVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiXSkpLA0KICAgICAgICAgICAgIlBQQVNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSkpLCANCiAgICAgICAgICAgICJQUEFTT1Q1ZGF5c0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFPjVdKSksDQogICAgICAgICAgICAiV1RQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0qREFZU19MQVRFW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+PTFdKSkpICU+JSAgDQogIHNlbGVjdChTaGlwQ2FuY2VsTW9udGgsIA0KICAgICAgICAgUmVwb3J0aW5nQnJhbmQsIA0KICAgICAgICAgU09UVW5pdHMsIA0KICAgICAgICAgU09UT25UaW1lVW5pdHMsIA0KICAgICAgICAgU09UTGF0ZVVuaXRzLCANCiAgICAgICAgIFNPVExhdGU1ZGF5c1VuaXRzLCANCiAgICAgICAgIFdUU09UTGF0ZVVuaXRzLCANCiAgICAgICAgIFBQQVVuaXRzLA0KICAgICAgICAgUFBBU09UTGF0ZVVuaXRzLA0KICAgICAgICAgUFBBU09UNWRheXNMYXRlVW5pdHMsDQogICAgICAgICBXVFBQQVNPVExhdGVVbml0cykNCiMgVmlldyhNb250aGx5X0JyYW5kX1NPVCkNCg0KIyBDcmVhdGUgTW9udGhseSBTT1QgQ2F0ZWdvcnkgVGFibGUgLS0tLQ0KTW9udGhseV9DYXRlZ29yeV9TT1QgPC0gU09UX01hc3RlciAlPiUNCiAgZmlsdGVyKFNPVF9NYXN0ZXIkU2hpcENhbmNlbFdlZWsgPD0gRU9XKSAlPiUNCiAgZ3JvdXBfYnkoU2hpcENhbmNlbE1vbnRoLCBDYXRlZ29yeSkgJT4lIA0KICBzdW1tYXJpc2UoIlNPVFVuaXRzIiA9IGZsb29yKHN1bShVbml0cykpLA0KICAgICAgICAgICAgIlNPVE9uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiU09UTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAiU09UTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPiA1XSkpLCANCiAgICAgICAgICAgICJXVFNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0qREFZU19MQVRFW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpLA0KICAgICAgICAgICAgIlBQQVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIl0pKSwNCiAgICAgICAgICAgICJQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSwgDQogICAgICAgICAgICAiUFBBU09UNWRheXNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURT41XSkpLA0KICAgICAgICAgICAgIldUUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpKSAlPiUgIA0KICBzZWxlY3QoU2hpcENhbmNlbE1vbnRoLCANCiAgICAgICAgIENhdGVnb3J5LCANCiAgICAgICAgIFNPVFVuaXRzLCANCiAgICAgICAgIFNPVE9uVGltZVVuaXRzLCANCiAgICAgICAgIFNPVExhdGVVbml0cywgDQogICAgICAgICBTT1RMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVFNPVExhdGVVbml0cywgDQogICAgICAgICBQUEFVbml0cywNCiAgICAgICAgIFBQQVNPVExhdGVVbml0cywNCiAgICAgICAgIFBQQVNPVDVkYXlzTGF0ZVVuaXRzLA0KICAgICAgICAgV1RQUEFTT1RMYXRlVW5pdHMpDQojIFZpZXcoTW9udGhseV9DYXRlZ29yeV9TT1QpIA0KDQojIENyZWF0ZSBNb250aGx5IEdhcCBJbmMgU09UIFRhYmxlIC0tLS0NCk1vbnRobHlfR2FwSW5jX1NPVCA8LSBTT1RfTWFzdGVyICU+JQ0KICBmaWx0ZXIoU09UX01hc3RlciRTaGlwQ2FuY2VsV2VlayA8PSBFT1cpICU+JQ0KICBncm91cF9ieShTaGlwQ2FuY2VsTW9udGgpICU+JSANCiAgc3VtbWFyaXNlKCJTT1RVbml0cyIgPSBmbG9vcihzdW0oVW5pdHMpKSwNCiAgICAgICAgICAgICJTT1RPblRpbWVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkpLA0KICAgICAgICAgICAgIlNPVExhdGVVbml0cyI9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSkpLA0KICAgICAgICAgICAgIlNPVExhdGU1ZGF5c1VuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID4gNV0pKSwgDQogICAgICAgICAgICAiV1RTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID49MV0pKSwNCiAgICAgICAgICAgICJQUEFVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciJdKSksDQogICAgICAgICAgICAiUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKSksIA0KICAgICAgICAgICAgIlBQQVNPVDVkYXlzTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEU+NV0pKSwNCiAgICAgICAgICAgICJXVFBQQVNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSpEQVlTX0xBVEVbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID49MV0pKSkgJT4lICANCiAgc2VsZWN0KFNoaXBDYW5jZWxNb250aCwgDQogICAgICAgICBTT1RVbml0cywgDQogICAgICAgICBTT1RPblRpbWVVbml0cywgDQogICAgICAgICBTT1RMYXRlVW5pdHMsIA0KICAgICAgICAgU09UTGF0ZTVkYXlzVW5pdHMsIA0KICAgICAgICAgV1RTT1RMYXRlVW5pdHMsIA0KICAgICAgICAgUFBBVW5pdHMsDQogICAgICAgICBQUEFTT1RMYXRlVW5pdHMsDQogICAgICAgICBQUEFTT1Q1ZGF5c0xhdGVVbml0cywNCiAgICAgICAgIFdUUFBBU09UTGF0ZVVuaXRzKQ0KIyBWaWV3KE1vbnRobHlfR2FwSW5jX1NPVCkgDQoNCiMgQ3JlYXRlIE1vbnRobHkgT1RTIEJyYW5kIGFuZCBDYXRlZ29yeSBUYWJsZSAtLS0tDQpNb250aGx5X0JyYW5kX0NhdGVnb3J5X09UUyA8LSBPVFNfTWFzdGVyICU+JQ0KICBmaWx0ZXIoT1RTX01hc3RlciRXZWVrIDw9IEVPVykgJT4lDQogIGdyb3VwX2J5KE1vbnRoX051bWJlciwgUmVwb3J0aW5nQnJhbmQsIENhdGVnb3J5KSAlPiUgDQogIHN1bW1hcmlzZSgiT1RTVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzKSksDQogICAgICAgICAgICAiT1RTT25UaW1lVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iT25UaW1lIl0pKSwNCiAgICAgICAgICAgICJPVFNMYXRlVW5pdHMiPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0pKSwNCiAgICAgICAgICAgICJPVFNMYXRlNWRheXNVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIiAmIERheXNfTGF0ZSA+IDVdKSksIA0KICAgICAgICAgICAgIldUT1RTTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSpEYXlzX0xhdGVbTGF0ZW5lc3M9PSJMYXRlIiAmIERheXNfTGF0ZSA+PTFdKSksDQogICAgICAgICAgICAiUFBBT1RTTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKSkpICU+JSAgDQogIHNlbGVjdChNb250aF9OdW1iZXIsIA0KICAgICAgICAgUmVwb3J0aW5nQnJhbmQsIA0KICAgICAgICAgQ2F0ZWdvcnksIA0KICAgICAgICAgT1RTVW5pdHMsIA0KICAgICAgICAgT1RTT25UaW1lVW5pdHMsIA0KICAgICAgICAgT1RTTGF0ZVVuaXRzLCANCiAgICAgICAgIE9UU0xhdGU1ZGF5c1VuaXRzLCANCiAgICAgICAgIFdUT1RTTGF0ZVVuaXRzLCANCiAgICAgICAgIFBQQU9UU0xhdGVVbml0cykNCiAjIFZpZXcoTW9udGhseV9CcmFuZF9DYXRlZ29yeV9PVFMpDQoNCiMgQ3JlYXRlIE1vbnRobHkgT1RTIEJyYW5kIFRhYmxlIC0tLS0NCk1vbnRobHlfQnJhbmRfT1RTIDwtIE9UU19NYXN0ZXIgJT4lDQogIGZpbHRlcihPVFNfTWFzdGVyJFdlZWsgPD0gRU9XKSAlPiUNCiAgZ3JvdXBfYnkoTW9udGhfTnVtYmVyLCBSZXBvcnRpbmdCcmFuZCkgJT4lIA0KICBzdW1tYXJpc2UoIk9UU1VuaXRzIiA9IGZsb29yKHN1bShVbml0cykpLA0KICAgICAgICAgICAgIk9UU09uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiT1RTTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAiT1RTTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEYXlzX0xhdGUgPiA1XSkpLCANCiAgICAgICAgICAgICJXVE9UU0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0qRGF5c19MYXRlW0xhdGVuZXNzPT0iTGF0ZSIgJiBEYXlzX0xhdGUgPj0xXSkpLA0KICAgICAgICAgICAgIlBQQU9UU0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSkpKSAlPiUgIA0KICBzZWxlY3QoTW9udGhfTnVtYmVyLCANCiAgICAgICAgIFJlcG9ydGluZ0JyYW5kLCANCiAgICAgICAgIE9UU1VuaXRzLCANCiAgICAgICAgIE9UU09uVGltZVVuaXRzLCANCiAgICAgICAgIE9UU0xhdGVVbml0cywgDQogICAgICAgICBPVFNMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVE9UU0xhdGVVbml0cywgDQogICAgICAgICBQUEFPVFNMYXRlVW5pdHMpDQojIFZpZXcoTW9udGhseV9CcmFuZF9PVFMpDQoNCiMgQ3JlYXRlIE1vbnRobHkgT1RTIENhdGVnb3J5IFRhYmxlIC0tLS0NCk1vbnRobHlfQ2F0ZWdvcnlfT1RTIDwtIE9UU19NYXN0ZXIgJT4lDQogIGZpbHRlcihPVFNfTWFzdGVyJFdlZWsgPD0gRU9XKSAlPiUNCiAgZ3JvdXBfYnkoTW9udGhfTnVtYmVyLCBDYXRlZ29yeSkgJT4lIA0KICBzdW1tYXJpc2UoIk9UU1VuaXRzIiA9IGZsb29yKHN1bShVbml0cykpLA0KICAgICAgICAgICAgIk9UU09uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiT1RTTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAiT1RTTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEYXlzX0xhdGUgPiA1XSkpLCANCiAgICAgICAgICAgICJXVE9UU0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0qRGF5c19MYXRlW0xhdGVuZXNzPT0iTGF0ZSIgJiBEYXlzX0xhdGUgPj0xXSkpLA0KICAgICAgICAgICAgIlBQQU9UU0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSkpKSAlPiUgIA0KICBzZWxlY3QoTW9udGhfTnVtYmVyLCANCiAgICAgICAgIENhdGVnb3J5LCANCiAgICAgICAgIE9UU1VuaXRzLCANCiAgICAgICAgIE9UU09uVGltZVVuaXRzLCANCiAgICAgICAgIE9UU0xhdGVVbml0cywgDQogICAgICAgICBPVFNMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVE9UU0xhdGVVbml0cywgDQogICAgICAgICBQUEFPVFNMYXRlVW5pdHMpDQojIFZpZXcoTW9udGhseV9DYXRlZ29yeV9PVFMpDQoNCiMgQ3JlYXRlIE1vbnRobHkgR2FwIEluYyBPVFMgVGFibGUgLS0tLQ0KTW9udGhseV9HYXBJbmNfT1RTIDwtIE9UU19NYXN0ZXIgJT4lDQogIGZpbHRlcihPVFNfTWFzdGVyJFdlZWsgPD0gRU9XKSAlPiUNCiAgZ3JvdXBfYnkoTW9udGhfTnVtYmVyKSAlPiUgDQogIHN1bW1hcmlzZSgiT1RTVW5pdHMiID0gc3VtKFVuaXRzKSwNCiAgICAgICAgICAgICJPVFNPblRpbWVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkpLA0KICAgICAgICAgICAgIk9UU0xhdGVVbml0cyI9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSkpLA0KICAgICAgICAgICAgIk9UU0xhdGU1ZGF5c1VuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID4gNV0pKSwgDQogICAgICAgICAgICAiV1RPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRheXNfTGF0ZVtMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID49MV0pKSwNCiAgICAgICAgICAgICJQUEFPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSkgJT4lICANCiAgc2VsZWN0KE1vbnRoX051bWJlciwgDQogICAgICAgICBPVFNVbml0cywgDQogICAgICAgICBPVFNPblRpbWVVbml0cywgDQogICAgICAgICBPVFNMYXRlVW5pdHMsIA0KICAgICAgICAgT1RTTGF0ZTVkYXlzVW5pdHMsIA0KICAgICAgICAgV1RPVFNMYXRlVW5pdHMsIA0KICAgICAgICAgUFBBT1RTTGF0ZVVuaXRzKQ0KICMgVmlldyhNb250aGx5X0dhcEluY19PVFMpDQoNCiMgQ3JlYXRlIE1vbnRobHkgLSBQcmVmZXJyZWQgVmVuZG9yIC0gTmV3IC0tLS0NCk1vbnRobHlfUHJlZmVycmVkX1ZlbmRvcl9uZXcgPC0gaW5uZXJfam9pbihTT1RfTWFzdGVyLCBQcmVmZXJyZWRfVmVuZG9yX25ldywgYnkgPSBjKCJDYXRlZ29yeSI9ICJOZXcgQ2F0ZWdvcnkiLCAiUGFyZW50X1ZlbmRvciI9IlZlbmRvciBOYW1lIikpICU+JSANCiAgZmlsdGVyKFNoaXBDYW5jZWxXZWVrIDw9IEVPVykgJT4lDQogIGdyb3VwX2J5KENhdGVnb3J5LCBQYXJlbnRfVmVuZG9yLCBTaGlwQ2FuY2VsTW9udGgpICU+JSANCiAgc3VtbWFyaXNlKCJTT1RVbml0cyIgPSBmbG9vcihzdW0oVW5pdHMpKSwNCiAgICAgICAgICAgICJTT1RPblRpbWVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkpLA0KICAgICAgICAgICAgIlNPVExhdGVVbml0cyI9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSkpLA0KICAgICAgICAgICAgIlNPVExhdGU1ZGF5c1VuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID4gNV0pKSwgDQogICAgICAgICAgICAiV1RTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID49MV0pKSwNCiAgICAgICAgICAgICJQUEFVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciJdKSksDQogICAgICAgICAgICAiUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKSksIA0KICAgICAgICAgICAgIlBQQVNPVDVkYXlzTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEU+NV0pKSwNCiAgICAgICAgICAgICJXVFBQQVNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSpEQVlTX0xBVEVbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID49MV0pKSkgJT4lICANCiAgc2VsZWN0KENhdGVnb3J5LA0KICAgICAgICAgUGFyZW50X1ZlbmRvciwNCiAgICAgICAgIFNoaXBDYW5jZWxNb250aCwNCiAgICAgICAgIFNPVFVuaXRzLCANCiAgICAgICAgIFNPVE9uVGltZVVuaXRzLCANCiAgICAgICAgIFNPVExhdGVVbml0cywgDQogICAgICAgICBTT1RMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVFNPVExhdGVVbml0cywgDQogICAgICAgICBQUEFVbml0cywNCiAgICAgICAgIFBQQVNPVExhdGVVbml0cywNCiAgICAgICAgIFBQQVNPVDVkYXlzTGF0ZVVuaXRzLA0KICAgICAgICAgV1RQUEFTT1RMYXRlVW5pdHMpICU+JSANCiAgYXJyYW5nZShTaGlwQ2FuY2VsTW9udGgsIENhdGVnb3J5KQ0KIyBDcmVhdGUgTW9udGhseSBQcmVmZXJyZWQgVmVuZG9yIC0gTmV3IE9UUyAtLS0tDQpNb250aGx5X1ByZWZlcnJlZF9WZW5kb3JfTmV3X09UUyA8LSBpbm5lcl9qb2luKE9UU19NYXN0ZXIsIFByZWZlcnJlZF9WZW5kb3JfbmV3LCBieSA9IGMoIkNhdGVnb3J5Ij0gIk5ldyBDYXRlZ29yeSIsICJQYXJlbnRfVmVuZG9yIj0iVmVuZG9yIE5hbWUiKSkgJT4lIA0KICBmaWx0ZXIoV2VlayA8PSBFT1cpICU+JQ0KICBncm91cF9ieShDYXRlZ29yeSwgUGFyZW50X1ZlbmRvciwgIE1vbnRoX051bWJlciApICU+JSANCiAgc3VtbWFyaXNlKCJPVFNVbml0cyIgPSBmbG9vcihzdW0oVW5pdHMpKSwNCiAgICAgICAgICAgICJPVFNPblRpbWVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkpLA0KICAgICAgICAgICAgIk9UU0xhdGVVbml0cyI9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSkpLA0KICAgICAgICAgICAgIk9UU0xhdGU1ZGF5c1VuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID4gNV0pKSwgDQogICAgICAgICAgICAiV1RPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRheXNfTGF0ZVtMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID49MV0pKSwNCiAgICAgICAgICAgICJQUEFPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSkgJT4lICANCiAgc2VsZWN0KENhdGVnb3J5LCANCiAgICAgICAgIFBhcmVudF9WZW5kb3IsDQogICAgICAgICBNb250aF9OdW1iZXIsDQogICAgICAgICBPVFNVbml0cywgDQogICAgICAgICBPVFNPblRpbWVVbml0cywgDQogICAgICAgICBPVFNMYXRlVW5pdHMsIA0KICAgICAgICAgT1RTTGF0ZTVkYXlzVW5pdHMsIA0KICAgICAgICAgV1RPVFNMYXRlVW5pdHMsIA0KICAgICAgICAgUFBBT1RTTGF0ZVVuaXRzKSAlPiUgDQogIGFycmFuZ2UoTW9udGhfTnVtYmVyLCBDYXRlZ29yeSkNCiMgVmlldyhNb250aGx5X1ByZWZlcnJlZF9WZW5kb3JfTmV3X09UUykNCg0KDQojIENyZWF0ZSBNb250aGx5IEJyYW5kIGFuZCBDYXRlZ29yeSBDb21iaW5lIFRhYmxlIC0tLS0NCk1vbnRobHlfQnJhbmRfQ2F0ZWdvcnlfQ29tYmluZSA8LSBsZWZ0X2pvaW4oTW9udGhseV9CcmFuZF9DYXRlZ29yeV9TT1QsIE1vbnRobHlfQnJhbmRfQ2F0ZWdvcnlfT1RTLCBieT0gYygiU2hpcENhbmNlbE1vbnRoIj0iTW9udGhfTnVtYmVyIiwgIlJlcG9ydGluZ0JyYW5kIj0iUmVwb3J0aW5nQnJhbmQiLCAiQ2F0ZWdvcnkiPSJDYXRlZ29yeSIpKQ0KTW9udGhseV9CcmFuZF9DYXRlZ29yeV9Db21iaW5lIDwtIE1vbnRobHlfQnJhbmRfQ2F0ZWdvcnlfQ29tYmluZVtjKDE6OCwgMTM6MTcsOToxMCwxOCwxMToxMildDQoNCiMgQ3JlYXRlIE1vbnRobHkgU09UIEJyYW5kIENvbWJpbmUgVGFibGUgLS0tLQ0KTW9udGhseV9CcmFuZF9Db21iaW5lIDwtIGxlZnRfam9pbihNb250aGx5X0JyYW5kX1NPVCwgTW9udGhseV9CcmFuZF9PVFMsIGJ5PSBjKCJTaGlwQ2FuY2VsTW9udGgiPSJNb250aF9OdW1iZXIiLCAiUmVwb3J0aW5nQnJhbmQiPSJSZXBvcnRpbmdCcmFuZCIpKQ0KTW9udGhseV9CcmFuZF9Db21iaW5lIDwtIE1vbnRobHlfQnJhbmRfQ29tYmluZVtjKDE6NywgMTI6MTYsIDg6OSwgMTcsIDEwOjExKV0NCiMgVmlldyhNb250aGx5X0JyYW5kX0NvbWJpbmUpDQoNCiMgQ3JlYXRlIE1vbnRobHkgU09UIENhdGVnb3J5IENvbWJpbmUgVGFibGUgLS0tLQ0KTW9udGhseV9DYXRlZ29yeV9Db21iaW5lIDwtIGxlZnRfam9pbihNb250aGx5X0NhdGVnb3J5X1NPVCwgTW9udGhseV9DYXRlZ29yeV9PVFMsIGJ5PSBjKCJTaGlwQ2FuY2VsTW9udGgiPSJNb250aF9OdW1iZXIiLCAiQ2F0ZWdvcnkiPSJDYXRlZ29yeSIpKQ0KTW9udGhseV9DYXRlZ29yeV9Db21iaW5lIDwtIE1vbnRobHlfQ2F0ZWdvcnlfQ29tYmluZVtjKDE6NywgMTI6MTYsIDg6OSwgMTcsIDEwOjExKV0NCiMgVmlldyhNb250aGx5X0NhdGVnb3J5X0NvbWJpbmUpDQoNCiMgQ3JlYXRlIE1vbnRobHkgU09UIEdhcCBJbmMgQ29tYmluZSBUYWJsZSAtLS0tDQpNb250aGx5X0dhcEluY19Db21iaW5lIDwtIGxlZnRfam9pbihNb250aGx5X0dhcEluY19TT1QsIE1vbnRobHlfR2FwSW5jX09UUywgYnk9IGMoIlNoaXBDYW5jZWxNb250aCI9Ik1vbnRoX051bWJlciIpKQ0KTW9udGhseV9HYXBJbmNfQ29tYmluZSA8LSBNb250aGx5X0dhcEluY19Db21iaW5lW2MoMTo2LCAxMToxNSw3OjgsMTYsOToxMCldDQojIFZpZXcoTW9udGhseV9HYXBJbmNfQ29tYmluZSkNCiMgQ3JlYXRlIFByZWZlcnJlZCBWZW5kb3IgQ29tYmluZSBUYWJsZSAtLS0tDQpQcmVmZXJyZWRfVmVuZG9yX05ld19Db21iaW5lIDwtIGxlZnRfam9pbihNb250aGx5X1ByZWZlcnJlZF9WZW5kb3JfbmV3LCBNb250aGx5X1ByZWZlcnJlZF9WZW5kb3JfTmV3X09UUywgYnkgPSBjKCJDYXRlZ29yeSI9IkNhdGVnb3J5IiwgIlBhcmVudF9WZW5kb3IiPSJQYXJlbnRfVmVuZG9yIiwgIlNoaXBDYW5jZWxNb250aCIgPSAiTW9udGhfTnVtYmVyIikpDQpQcmVmZXJyZWRfVmVuZG9yX05ld19Db21iaW5lIDwtUHJlZmVycmVkX1ZlbmRvcl9OZXdfQ29tYmluZVtjKDE6OCwgMTM6MTcsIDk6MTAsIDE4LCAxMToxMildDQoNCiMgQ3JlYXRlIE1vbnRobHkgLSBieURDDQpNb250aGx5X2J5X0RDIDwtIE9UU19NYXN0ZXIgJT4lIA0KICBmaWx0ZXIoT1RTX01hc3RlciRXZWVrIDw9IEVPVykgJT4lDQogIGdyb3VwX2J5KEZpc2NhbF9Nb250aCwgTW9udGhfTnVtYmVyLCBEQ0NhbXB1cywgRENfTkFNRSwgRGVzdEN0cnlDRCkgJT4lIA0KICBzdW1tYXJpc2UoIlRvdGFsIFVuaXRzIiA9IGZsb29yKHN1bShVbml0cykpLA0KICAgICAgICAgICAgIk9uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiT1RTJSIgPSBzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkvc3VtKFVuaXRzKSwNCiAgICAgICAgICAgICJPVFNMYXRlNWRheXNVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIiAmIERheXNfTGF0ZSA+IDVdKSksDQogICAgICAgICAgICAiV1RPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRheXNfTGF0ZVtMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID49MV0pKSwNCiAgICAgICAgICAgICJMYXRlVW5pdHMiPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0pKSkgJT4lIA0KICBzZWxlY3QoRmlzY2FsX01vbnRoLCANCiAgICAgICAgIE1vbnRoX051bWJlciwgDQogICAgICAgICBgT25UaW1lVW5pdHNgLCANCiAgICAgICAgIGBUb3RhbCBVbml0c2AsIA0KICAgICAgICAgRENDYW1wdXMsIA0KICAgICAgICAgRENfTkFNRSwgDQogICAgICAgICBEZXN0Q3RyeUNELCANCiAgICAgICAgIGBPVFMlYCwgDQogICAgICAgICBgT1RTTGF0ZTVkYXlzVW5pdHNgLA0KICAgICAgICAgYFdUT1RTTGF0ZVVuaXRzYCwgDQogICAgICAgICBgTGF0ZVVuaXRzYCkNCiMgQ3JlYXRlIFRvcCAyMCBDb3VudHJpZXMgU09UIC0tLS0NCk1vbnRobHlfVG9wXzIwX1NPVCA8LSBpbm5lcl9qb2luKFNPVF9NYXN0ZXIsIFRvcF8yMF9Db3VudHJpZXMsIGJ5ID0gYygiQ291bnRyeU9mT3JpZ2luIj0gIkNvdW50cnlPZk9yaWdpbiIpKQ0KTW9udGhseV9Ub3BfMjBfU09UIDwtIE1vbnRobHlfVG9wXzIwX1NPVCAlPiUNCiAgZmlsdGVyKFNoaXBDYW5jZWxXZWVrIDw9IEVPVykgJT4lDQogIGdyb3VwX2J5KFNoaXBDYW5jZWxNb250aCkgJT4lIA0KICBzdW1tYXJpc2UoIlNPVFVuaXRzIiA9IGZsb29yKHN1bShVbml0cykpLA0KICAgICAgICAgICAgIlNPVE9uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiU09UTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAiU09UTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPiA1XSkpLCANCiAgICAgICAgICAgICJXVFNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0qREFZU19MQVRFW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpLA0KICAgICAgICAgICAgIlBQQVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIl0pKSwNCiAgICAgICAgICAgICJQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSwgDQogICAgICAgICAgICAiUFBBU09UNWRheXNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURT41XSkpLA0KICAgICAgICAgICAgIldUUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpKSAlPiUgIA0KICBzZWxlY3QoU2hpcENhbmNlbE1vbnRoLCANCiAgICAgICAgIFNPVFVuaXRzLCANCiAgICAgICAgIFNPVE9uVGltZVVuaXRzLCANCiAgICAgICAgIFNPVExhdGVVbml0cywgDQogICAgICAgICBTT1RMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVFNPVExhdGVVbml0cywgDQogICAgICAgICBQUEFVbml0cywNCiAgICAgICAgIFBQQVNPVExhdGVVbml0cywNCiAgICAgICAgIFBQQVNPVDVkYXlzTGF0ZVVuaXRzLA0KICAgICAgICAgV1RQUEFTT1RMYXRlVW5pdHMpDQojIFZpZXcoTW9udGhseV9Ub3BfMjBfU09UKSANCg0KIyBDcmVhdGUgTW9udGhseSBUb3AgMjAgT1RTIFRhYmxlIC0tLS0NCk1vbnRobHlfVE9QXzIwX09UUyA8LSBpbm5lcl9qb2luKE9UU19NYXN0ZXIsIFRvcF8yMF9Db3VudHJpZXMsIGJ5ID0gYygiT1JJR0lOX0NPVU5UUllfQ09ERSI9IkNvdW50cnlPZk9yaWdpbiIpKQ0KTW9udGhseV9UT1BfMjBfT1RTIDwtIE1vbnRobHlfVE9QXzIwX09UUyAlPiUNCiAgZmlsdGVyKFdlZWsgPD0gRU9XKSAlPiUNCiAgZ3JvdXBfYnkoTW9udGhfTnVtYmVyKSAlPiUgDQogIHN1bW1hcmlzZSgiT1RTVW5pdHMiID0gc3VtKFVuaXRzKSwNCiAgICAgICAgICAgICJPVFNPblRpbWVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkpLA0KICAgICAgICAgICAgIk9UU0xhdGVVbml0cyI9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSkpLA0KICAgICAgICAgICAgIk9UU0xhdGU1ZGF5c1VuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID4gNV0pKSwgDQogICAgICAgICAgICAiV1RPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRheXNfTGF0ZVtMYXRlbmVzcz09IkxhdGUiICYgRGF5c19MYXRlID49MV0pKSwNCiAgICAgICAgICAgICJQUEFPVFNMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSkgJT4lICANCiAgc2VsZWN0KE1vbnRoX051bWJlciwgDQogICAgICAgICBPVFNVbml0cywgDQogICAgICAgICBPVFNPblRpbWVVbml0cywgDQogICAgICAgICBPVFNMYXRlVW5pdHMsIA0KICAgICAgICAgT1RTTGF0ZTVkYXlzVW5pdHMsIA0KICAgICAgICAgV1RPVFNMYXRlVW5pdHMsIA0KICAgICAgICAgUFBBT1RTTGF0ZVVuaXRzKQ0KIyAgVmlldyhNb250aGx5X1RPUF8yMF9PVFMpDQojIENyZWF0ZSBNb250aGx5IFRvcCAyMCBDb21iaW5lIHRhYmxlIC0tLS0NCk1vbnRobHlfVG9wXzIwX0NvbWJpbmUgPC0gaW5uZXJfam9pbihNb250aGx5X1RvcF8yMF9TT1QsIE1vbnRobHlfVE9QXzIwX09UUywgYnk9IGMoIlNoaXBDYW5jZWxNb250aCI9Ik1vbnRoX051bWJlciIpKQ0KTW9udGhseV9Ub3BfMjBfQ29tYmluZSA8LSBNb250aGx5X1RvcF8yMF9Db21iaW5lW2MoMTo2LCAxMToxNSw3OjgsMTYsOToxMCldDQogIA0KIyBDcmVhdGUgTW9udGhseSBUb3AgNTAgVmVuZG9ycyBTT1QgVGFibGUgLS0tLQ0KTW9udGhseV9Ub3BfNTBfVmVuZG9yc19TT1QgPC0gaW5uZXJfam9pbihTT1RfTWFzdGVyLCBUb3BfNTBfVmVuZG9ycywgYnkgPSBjKCJQYXJlbnRfVmVuZG9yIj0gIlBhcmVudF9WZW5kb3IiKSkNCk1vbnRobHlfVG9wXzUwX1ZlbmRvcnNfU09UIDwtIE1vbnRobHlfVG9wXzUwX1ZlbmRvcnNfU09UICU+JQ0KICBmaWx0ZXIoU2hpcENhbmNlbFdlZWsgPD0gRU9XKSAlPiUNCiAgZ3JvdXBfYnkoU2hpcENhbmNlbE1vbnRoKSAlPiUgDQogIHN1bW1hcmlzZSgiU09UVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzKSksDQogICAgICAgICAgICAiU09UT25UaW1lVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iT25UaW1lIl0pKSwNCiAgICAgICAgICAgICJTT1RMYXRlVW5pdHMiPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0pKSwNCiAgICAgICAgICAgICJTT1RMYXRlNWRheXNVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+IDVdKSksIA0KICAgICAgICAgICAgIldUU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSpEQVlTX0xBVEVbTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+PTFdKSksDQogICAgICAgICAgICAiUFBBVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiXSkpLA0KICAgICAgICAgICAgIlBQQVNPVExhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSkpLCANCiAgICAgICAgICAgICJQUEFTT1Q1ZGF5c0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFPjVdKSksDQogICAgICAgICAgICAiV1RQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0qREFZU19MQVRFW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+PTFdKSkpICU+JSAgDQogIHNlbGVjdChTaGlwQ2FuY2VsTW9udGgsIA0KICAgICAgICAgU09UVW5pdHMsIA0KICAgICAgICAgU09UT25UaW1lVW5pdHMsIA0KICAgICAgICAgU09UTGF0ZVVuaXRzLCANCiAgICAgICAgIFNPVExhdGU1ZGF5c1VuaXRzLCANCiAgICAgICAgIFdUU09UTGF0ZVVuaXRzLCANCiAgICAgICAgIFBQQVVuaXRzLA0KICAgICAgICAgUFBBU09UTGF0ZVVuaXRzLA0KICAgICAgICAgUFBBU09UNWRheXNMYXRlVW5pdHMsDQogICAgICAgICBXVFBQQVNPVExhdGVVbml0cykNCiAjIFZpZXcoTW9udGhseV9Ub3BfNTBfVmVuZG9yc19TT1QpIA0KIyBDcmVhdGUgTW9udGhseSBUb3AgNTAgVmVuZG9ycyBPVFMgVGFibGUgLS0tLQ0KTW9udGhseV9Ub3BfNTBfVmVuZG9yc19PVFMgPC0gaW5uZXJfam9pbihPVFNfTWFzdGVyLCBUb3BfNTBfVmVuZG9ycywgYnkgPSBjKCJQYXJlbnRfVmVuZG9yIj0gIlBhcmVudF9WZW5kb3IiKSkNCk1vbnRobHlfVG9wXzUwX1ZlbmRvcnNfT1RTIDwtIE1vbnRobHlfVG9wXzUwX1ZlbmRvcnNfT1RTICU+JQ0KICBmaWx0ZXIoV2VlayA8PSBFT1cpICU+JQ0KICBncm91cF9ieShNb250aF9OdW1iZXIpICU+JSANCiAgc3VtbWFyaXNlKCJPVFNVbml0cyIgPSBzdW0oVW5pdHMpLA0KICAgICAgICAgICAgIk9UU09uVGltZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSksDQogICAgICAgICAgICAiT1RTTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAiT1RTTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEYXlzX0xhdGUgPiA1XSkpLCANCiAgICAgICAgICAgICJXVE9UU0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0qRGF5c19MYXRlW0xhdGVuZXNzPT0iTGF0ZSIgJiBEYXlzX0xhdGUgPj0xXSkpLA0KICAgICAgICAgICAgIlBQQU9UU0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiXSkpKSAlPiUgIA0KICBzZWxlY3QoTW9udGhfTnVtYmVyLCANCiAgICAgICAgIE9UU1VuaXRzLCANCiAgICAgICAgIE9UU09uVGltZVVuaXRzLCANCiAgICAgICAgIE9UU0xhdGVVbml0cywgDQogICAgICAgICBPVFNMYXRlNWRheXNVbml0cywgDQogICAgICAgICBXVE9UU0xhdGVVbml0cywgDQogICAgICAgICBQUEFPVFNMYXRlVW5pdHMpDQogIyBWaWV3KE1vbnRobHlfR2FwSW5jX09UUykNCg0KDQojIENyZWF0ZSBNb250aGx5IFNPVCBUb3AgNTAgVmVuZG9ycyBDb21iaW5lIFRhYmxlIC0tLS0NCk1vbnRobHlfVG9wXzUwX1ZlbmRvcnNfQ29tYmluZSA8LSBsZWZ0X2pvaW4oTW9udGhseV9Ub3BfNTBfVmVuZG9yc19TT1QsIE1vbnRobHlfVG9wXzUwX1ZlbmRvcnNfT1RTLCBieT0gYygiU2hpcENhbmNlbE1vbnRoIj0iTW9udGhfTnVtYmVyIikpDQpNb250aGx5X1RvcF81MF9WZW5kb3JzX0NvbWJpbmUgPC0gTW9udGhseV9Ub3BfNTBfVmVuZG9yc19Db21iaW5lW2MoMTo2LCAxMToxNSw3OjgsMTYsOToxMCldDQojIFZpZXcoTW9udGhseV9Ub3BfNTBfX1ZlbmRvcnNfQ29tYmluZSkNCiMgQ3JlYXRlIE9UU3ZzU09UIHRhYmxlIC0tLS0NCiBPVFNfdnMgPC0gT1RTX01hc3RlciAlPiUgDQogICBzZWxlY3QoTlVNQkVSX1NFUSwgTW9udGhfTnVtYmVyLCBMYXRlbmVzcywgVW5pdHMpICU+JQ0KICAgZmlsdGVyKExhdGVuZXNzIT0gIlVuZGV0ZXJtaW5lZCIpICU+JSANCiAgIHJlbmFtZSgiU3RvY2tlZE9uVGltZSIgPSBMYXRlbmVzcykgJT4lDQogICBncm91cF9ieShNb250aF9OdW1iZXIsIFN0b2NrZWRPblRpbWUpICU+JSANCiAgIGRyb3BsZXZlbHMoKQ0KIA0KIFNPVF92cyA8LSBTT1RfTWFzdGVyICU+JSANCiAgIHNlbGVjdChOVU1CRVJfU0VRLCBTaGlwQ2FuY2VsTW9udGgsIExhdGVuZXNzKSAlPiUNCiAgIGZpbHRlcihMYXRlbmVzcyE9IlVubWVhc3VyZWQiKSAlPiUgDQogICByZW5hbWUoIlNoaXBwZWRPblRpbWUiID0gTGF0ZW5lc3MpICU+JQ0KICAgZ3JvdXBfYnkoU2hpcENhbmNlbE1vbnRoLCBTaGlwcGVkT25UaW1lKSAlPiUgDQogICBkcm9wbGV2ZWxzKCkNCiANCiBPVFN2c1NPVCA8LSBpbm5lcl9qb2luKE9UU192cywgU09UX3ZzLCBieSA9IGMoIk5VTUJFUl9TRVEiPSAiTlVNQkVSX1NFUSIpKSAlPiUNCiAgIGdyb3VwX2J5KE1vbnRoX051bWJlciwgU3RvY2tlZE9uVGltZSwgU2hpcHBlZE9uVGltZSkgJT4lIA0KICAgc3VtbWFyaXNlKCJTdW1PZlVuaXRzIiA9IGZsb29yKHN1bShVbml0cykpKQ0KIA0KIyBDcmVhdGUgTW9udGhseSBCcmFuZCBUb3AgMTAgRGVsYXkgQ29tYmluZSAtLS0tDQpCcmFuZF9Ub3BfVGVuX0RlbGF5IDwtICBTT1RfTWFzdGVyICU+JSANCiAgIGZpbHRlcihTaGlwQ2FuY2VsV2VlayA8PSBFT1cpICU+JQ0KICAgZ3JvdXBfYnkoUmVwb3J0aW5nQnJhbmQsIFNoaXBDYW5jZWxNb250aCwgUGFyZW50X1ZlbmRvcikgJT4lIA0KICAgc3VtbWFyaXNlKCJTT1RVbml0cyIgPSBmbG9vcihzdW0oVW5pdHMpKSwNCiAgICAgICAgICAgICAiQWRqdXN0ZWRTT1RVbml0cyI9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09Ik9uVGltZSJdKSArIHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSkpLA0KICAgICAgICAgICAgICJTT1RPblRpbWVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkpLA0KICAgICAgICAgICAgICJTT1RMYXRlVW5pdHMiPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0pKSwNCiAgICAgICAgICAgICAiU09UTGF0ZTVkYXlzVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPiA1XSkpLCANCiAgICAgICAgICAgICAiV1RTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID49MV0pKSwNCiAgICAgICAgICAgICAiUFBBVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiXSkpLA0KICAgICAgICAgICAgICJQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0pKSwgDQogICAgICAgICAgICAgIlBQQVNPVDVkYXlzTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEU+NV0pKSwNCiAgICAgICAgICAgICAiV1RQUEFTT1RMYXRlVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIl0qREFZU19MQVRFW1NIUF9NT0RFX0NBVEdfTk0gPT0gIlByZXBhaWRBaXIiICYgTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+PTFdKSkpICU+JSAgDQogICBzZWxlY3QoDQogICAgICAgICAgUmVwb3J0aW5nQnJhbmQsDQogICAgICAgICAgU2hpcENhbmNlbE1vbnRoLA0KICAgICAgICAgIFBhcmVudF9WZW5kb3IsDQogICAgICAgICAgU09UVW5pdHMsDQogICAgICAgICAgQWRqdXN0ZWRTT1RVbml0cywNCiAgICAgICAgICBTT1RPblRpbWVVbml0cywgDQogICAgICAgICAgU09UTGF0ZVVuaXRzLCANCiAgICAgICAgICBTT1RMYXRlNWRheXNVbml0cywgDQogICAgICAgICAgV1RTT1RMYXRlVW5pdHMpICU+JSANCiAgIHRvcF9uKDEwLCBTT1RMYXRlVW5pdHMpICU+JSANCiAgIGFycmFuZ2UoUmVwb3J0aW5nQnJhbmQsU2hpcENhbmNlbE1vbnRoLCBkZXNjKFNPVExhdGVVbml0cykpDQogICANCiMgQ3JlYXRlIE1vbnRobHkgQ2F0ZWdvcnkgVG9wIDEwIERlbGF5IENvbWJpbmUgLS0tLQ0KQ2F0ZWdvcnlfVG9wX1Rlbl9EZWxheSA8LSAgU09UX01hc3RlciAlPiUgDQogICBmaWx0ZXIoU2hpcENhbmNlbFdlZWsgPD0gRU9XKSAlPiUNCiAgIGdyb3VwX2J5KENhdGVnb3J5LCBTaGlwQ2FuY2VsTW9udGgsIFBhcmVudF9WZW5kb3IpICU+JSANCiAgIHN1bW1hcmlzZSgiU09UVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzKSksDQogICAgICAgICAgICAgIkFkanVzdGVkU09UVW5pdHMiPSBmbG9vcihzdW0oVW5pdHNbTGF0ZW5lc3M9PSJPblRpbWUiXSkgKyBzdW0oVW5pdHNbTGF0ZW5lc3M9PSJMYXRlIl0pKSwNCiAgICAgICAgICAgICAiU09UT25UaW1lVW5pdHMiID0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iT25UaW1lIl0pKSwNCiAgICAgICAgICAgICAiU09UTGF0ZVVuaXRzIj0gZmxvb3Ioc3VtKFVuaXRzW0xhdGVuZXNzPT0iTGF0ZSJdKSksDQogICAgICAgICAgICAgIlNPVExhdGU1ZGF5c1VuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFID4gNV0pKSwgDQogICAgICAgICAgICAgIldUU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tMYXRlbmVzcz09IkxhdGUiXSpEQVlTX0xBVEVbTGF0ZW5lc3M9PSJMYXRlIiAmIERBWVNfTEFURSA+PTFdKSksDQogICAgICAgICAgICAgIlBQQVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIl0pKSwNCiAgICAgICAgICAgICAiUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKSksIA0KICAgICAgICAgICAgICJQUEFTT1Q1ZGF5c0xhdGVVbml0cyIgPSBmbG9vcihzdW0oVW5pdHNbU0hQX01PREVfQ0FUR19OTSA9PSAiUHJlcGFpZEFpciIgJiBMYXRlbmVzcz09IkxhdGUiICYgREFZU19MQVRFPjVdKSksDQogICAgICAgICAgICAgIldUUFBBU09UTGF0ZVVuaXRzIiA9IGZsb29yKHN1bShVbml0c1tTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSJdKkRBWVNfTEFURVtTSFBfTU9ERV9DQVRHX05NID09ICJQcmVwYWlkQWlyIiAmIExhdGVuZXNzPT0iTGF0ZSIgJiBEQVlTX0xBVEUgPj0xXSkpKSAlPiUgIA0KICAgc2VsZWN0KA0KICAgICAgICAgIENhdGVnb3J5LA0KICAgICAgICAgIFNoaXBDYW5jZWxNb250aCwNCiAgICAgICAgICBQYXJlbnRfVmVuZG9yLA0KICAgICAgICAgIFNPVFVuaXRzLA0KICAgICAgICAgIEFkanVzdGVkU09UVW5pdHMsDQogICAgICAgICAgU09UT25UaW1lVW5pdHMsIA0KICAgICAgICAgIFNPVExhdGVVbml0cywgDQogICAgICAgICAgU09UTGF0ZTVkYXlzVW5pdHMsIA0KICAgICAgICAgIFdUU09UTGF0ZVVuaXRzKSAlPiUgDQogICB0b3BfbigxMCwgU09UTGF0ZVVuaXRzKSAlPiUgDQogICBhcnJhbmdlKENhdGVnb3J5LCBTaGlwQ2FuY2VsTW9udGgsIGRlc2MoU09UTGF0ZVVuaXRzKSkNCiAgIA0KIyBXcml0ZSB0YWJsZXMgLS0tLQ0Kd3JpdGVfY3N2KE1vbnRobHlfQnJhbmRfQ2F0ZWdvcnlfQ29tYmluZSwgDQogICAgICAgICAgcGF0aCA9IHBhc3RlKFNPVF9PVFNfZGlyZWN0b3J5LCAgDQogICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCdNb250aGx5X0JyYW5kX0NhdGVnb3J5X0NvbWJpbmVfV0VfJywgRU9XLCAnLmNzdicsc2VwID0gIiIpLCBzZXAgPSAnLycgKSkNCndyaXRlX2NzdihNb250aGx5X0JyYW5kX0NvbWJpbmUsIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnTW9udGhseV9CcmFuZF9Db21iaW5lX1dFXycsIEVPVywgJy5jc3YnLHNlcCA9ICIiKSwgc2VwID0gJy8nICkpDQp3cml0ZV9jc3YoTW9udGhseV9DYXRlZ29yeV9Db21iaW5lLCANCiAgICAgICAgICBwYXRoID0gcGFzdGUoU09UX09UU19kaXJlY3RvcnksICANCiAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoJ01vbnRobHlfQ2F0ZWdvcnlfQ29tYmluZV9XRV8nLCBFT1csICcuY3N2JyxzZXAgPSAiIiksIHNlcCA9ICcvJyApKQ0Kd3JpdGVfY3N2KE1vbnRobHlfR2FwSW5jX0NvbWJpbmUsIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnTW9udGhseV9HYXBJbmNfQ29tYmluZV9XRV8nLCBFT1csICcuY3N2JyxzZXAgPSAiIiksIHNlcCA9ICcvJyApKQ0Kd3JpdGVfY3N2KFByZWZlcnJlZF9WZW5kb3JfTmV3X0NvbWJpbmUsIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnUHJlZmVycmVkX1ZlbmRvcl9OZXdfQ29tYmluZV9XRV8nLCBFT1csICcuY3N2JyxzZXAgPSAiIiksIHNlcCA9ICcvJyApKQ0Kd3JpdGVfY3N2KE1vbnRobHlfYnlfREMsIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnTW9udGhseV9ieV9EQ19XRV8nLCBFT1csICcuY3N2JyxzZXAgPSAiIiksIHNlcCA9ICcvJyApKQ0Kd3JpdGVfY3N2KE1vbnRobHlfVG9wXzIwX0NvbWJpbmUsIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnTW9udGhseV9Ub3BfMjBfQ291bnRyaWVzX1dFXycsIEVPVywgJy5jc3YnLHNlcCA9ICIiKSwgc2VwID0gJy8nICkpDQp3cml0ZV9jc3YoTW9udGhseV9Ub3BfNTBfVmVuZG9yc19Db21iaW5lLCANCiAgICAgICAgICBwYXRoID0gcGFzdGUoU09UX09UU19kaXJlY3RvcnksICANCiAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoJ01vbnRobHlfVG9wXzUwX1ZlbmRvcnNfV0VfJywgRU9XLCAnLmNzdicsc2VwID0gIiIpLCBzZXAgPSAnLycgKSkNCndyaXRlX2NzdihPVFN2c1NPVCwgDQogICAgICAgICAgcGF0aCA9IHBhc3RlKFNPVF9PVFNfZGlyZWN0b3J5LCAgDQogICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCdPVFN2c1NPVF9XRV8nLCBFT1csICcuY3N2JyxzZXAgPSAiIiksIHNlcCA9ICcvJyApKQ0Kd3JpdGVfY3N2KEJyYW5kX1RvcF9UZW5fRGVsYXksIA0KICAgICAgICAgIHBhdGggPSBwYXN0ZShTT1RfT1RTX2RpcmVjdG9yeSwgIA0KICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgnQnJhbmRfVG9wXzEwX0RlbGF5X1dFXycsIEVPVywgJy5jc3YnLHNlcCA9ICIiKSwgc2VwID0gJy8nICkpDQp3cml0ZV9jc3YoQ2F0ZWdvcnlfVG9wX1Rlbl9EZWxheSwgDQogICAgICAgICAgcGF0aCA9IHBhc3RlKFNPVF9PVFNfZGlyZWN0b3J5LCAgDQogICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCdDYXRlZ29yeV9Ub3BfMTBfRGVsYXlfV0VfJywgRU9XLCAnLmNzdicsc2VwID0gIiIpLCBzZXAgPSAnLycgKSkNCg0KDQpgYGANCg0K